ANALYSE DES VENTES D’UN SITE DE E-COMMERCE¶
Import et installation¶
import pandas as pd
import numpy as np
import re
import matplotlib.pyplot as plt
import seaborn as sns
import skimpy
from skimpy import skim
import plotly.express as px
Création du DataFrame de base¶
data = pd.read_csv("shopping_trends.csv", sep=",", low_memory=False)
df = data.copy()
df.shape
(3900, 19)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3900 entries, 0 to 3899
Data columns (total 19 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Customer ID 3900 non-null int64
1 Age 3900 non-null int64
2 Gender 3900 non-null object
3 Item Purchased 3900 non-null object
4 Category 3900 non-null object
5 Purchase Amount (USD) 3900 non-null int64
6 Location 3900 non-null object
7 Size 3900 non-null object
8 Color 3900 non-null object
9 Season 3900 non-null object
10 Review Rating 3900 non-null float64
11 Subscription Status 3900 non-null object
12 Payment Method 3900 non-null object
13 Shipping Type 3900 non-null object
14 Discount Applied 3900 non-null object
15 Promo Code Used 3900 non-null object
16 Previous Purchases 3900 non-null int64
17 Preferred Payment Method 3900 non-null object
18 Frequency of Purchases 3900 non-null object
dtypes: float64(1), int64(4), object(14)
memory usage: 579.0+ KB
df.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| Customer ID | 3900.0 | 1950.500000 | 1125.977353 | 1.0 | 975.75 | 1950.5 | 2925.25 | 3900.0 |
| Age | 3900.0 | 44.068462 | 15.207589 | 18.0 | 31.00 | 44.0 | 57.00 | 70.0 |
| Purchase Amount (USD) | 3900.0 | 59.764359 | 23.685392 | 20.0 | 39.00 | 60.0 | 81.00 | 100.0 |
| Review Rating | 3900.0 | 3.749949 | 0.716223 | 2.5 | 3.10 | 3.7 | 4.40 | 5.0 |
| Previous Purchases | 3900.0 | 25.351538 | 14.447125 | 1.0 | 13.00 | 25.0 | 38.00 | 50.0 |
df.describe(include="object").T
| count | unique | top | freq | |
|---|---|---|---|---|
| Gender | 3900 | 2 | Male | 2652 |
| Item Purchased | 3900 | 25 | Blouse | 171 |
| Category | 3900 | 4 | Clothing | 1737 |
| Location | 3900 | 50 | Montana | 96 |
| Size | 3900 | 4 | M | 1755 |
| Color | 3900 | 25 | Olive | 177 |
| Season | 3900 | 4 | Spring | 999 |
| Subscription Status | 3900 | 2 | No | 2847 |
| Payment Method | 3900 | 6 | Credit Card | 696 |
| Shipping Type | 3900 | 6 | Free Shipping | 675 |
| Discount Applied | 3900 | 2 | No | 2223 |
| Promo Code Used | 3900 | 2 | No | 2223 |
| Preferred Payment Method | 3900 | 6 | PayPal | 677 |
| Frequency of Purchases | 3900 | 7 | Every 3 Months | 584 |
skim(df)
╭──────────────────────────────────────────────── skimpy summary ─────────────────────────────────────────────────╮ │ Data Summary Data Types │ │ ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┓ ┏━━━━━━━━━━━━━┳━━━━━━━┓ │ │ ┃ dataframe ┃ Values ┃ ┃ Column Type ┃ Count ┃ │ │ ┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━┩ ┡━━━━━━━━━━━━━╇━━━━━━━┩ │ │ │ Number of rows │ 3900 │ │ string │ 14 │ │ │ │ Number of columns │ 19 │ │ int64 │ 4 │ │ │ └───────────────────┴────────┘ │ float64 │ 1 │ │ │ └─────────────┴───────┘ │ │ number │ │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━┳━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━━┓ │ │ ┃ column_name ┃ NA ┃ NA % ┃ mean ┃ sd ┃ p0 ┃ p25 ┃ p50 ┃ p75 ┃ p100 ┃ hist ┃ │ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━╇━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━━┩ │ │ │ Customer ID │ 0 │ 0 │ 1950 │ 1126 │ 1 │ 975.8 │ 1950 │ 2925 │ 3900 │ ▇▇▇▇▇▇ │ │ │ │ Age │ 0 │ 0 │ 44.07 │ 15.21 │ 18 │ 31 │ 44 │ 57 │ 70 │ ▇▇▇▇▇▇ │ │ │ │ Purchase Amount (USD) │ 0 │ 0 │ 59.76 │ 23.69 │ 20 │ 39 │ 60 │ 81 │ 100 │ ▇▇▇▇▇▇ │ │ │ │ Review Rating │ 0 │ 0 │ 3.75 │ 0.7162 │ 2.5 │ 3.1 │ 3.7 │ 4.4 │ 5 │ ▇▇▇▇▇▇ │ │ │ │ Previous Purchases │ 0 │ 0 │ 25.35 │ 14.45 │ 1 │ 13 │ 25 │ 38 │ 50 │ ▇▇▇▇▇▇ │ │ │ └──────────────────────────┴─────┴───────┴────────┴──────────┴──────┴────────┴───────┴───────┴──────┴────────┘ │ │ string │ │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓ │ │ ┃ column_name ┃ NA ┃ NA % ┃ words per row ┃ total words ┃ │ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩ │ │ │ Gender │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Item Purchased │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Category │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Location │ 0 │ 0 │ 1.2 │ 4657 │ │ │ │ Size │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Color │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Season │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Subscription Status │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Payment Method │ 0 │ 0 │ 1.5 │ 5861 │ │ │ │ Shipping Type │ 0 │ 0 │ 1.8 │ 7148 │ │ │ │ Discount Applied │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Promo Code Used │ 0 │ 0 │ 1 │ 3900 │ │ │ │ Preferred Payment Method │ 0 │ 0 │ 1.5 │ 5819 │ │ │ │ Frequency of Purchases │ 0 │ 0 │ 1.3 │ 5068 │ │ │ └───────────────────────────────────────┴───────┴───────────┴──────────────────────────┴─────────────────────┘ │ ╰────────────────────────────────────────────────────── End ──────────────────────────────────────────────────────╯
Taux de remplissage des colonnes¶
# Calculer le taux de remplissage pour chaque colonne
column_fill_rates = df.notna().mean() * 100
# Afficher le taux de remplissage pour chaque colonne
column_fill_rates
Customer ID 100.0
Age 100.0
Gender 100.0
Item Purchased 100.0
Category 100.0
Purchase Amount (USD) 100.0
Location 100.0
Size 100.0
Color 100.0
Season 100.0
Review Rating 100.0
Subscription Status 100.0
Payment Method 100.0
Shipping Type 100.0
Discount Applied 100.0
Promo Code Used 100.0
Previous Purchases 100.0
Preferred Payment Method 100.0
Frequency of Purchases 100.0
dtype: float64
df.isnull().sum()
Customer ID 0
Age 0
Gender 0
Item Purchased 0
Category 0
Purchase Amount (USD) 0
Location 0
Size 0
Color 0
Season 0
Review Rating 0
Subscription Status 0
Payment Method 0
Shipping Type 0
Discount Applied 0
Promo Code Used 0
Previous Purchases 0
Preferred Payment Method 0
Frequency of Purchases 0
dtype: int64
L’ensemble des colonnes étant remplies et ne comportant aucune valeur nulle, nous pourrons faire une analyse complète des données.
Produits les plus vendus¶
item_purchased=df['Item Purchased'].value_counts().reset_index()
item_purchased
| Item Purchased | count | |
|---|---|---|
| 0 | Blouse | 171 |
| 1 | Pants | 171 |
| 2 | Jewelry | 171 |
| 3 | Shirt | 169 |
| 4 | Dress | 166 |
| 5 | Sweater | 164 |
| 6 | Jacket | 163 |
| 7 | Coat | 161 |
| 8 | Sunglasses | 161 |
| 9 | Belt | 161 |
| 10 | Sandals | 160 |
| 11 | Socks | 159 |
| 12 | Skirt | 158 |
| 13 | Scarf | 157 |
| 14 | Shorts | 157 |
| 15 | Hat | 154 |
| 16 | Handbag | 153 |
| 17 | Hoodie | 151 |
| 18 | Shoes | 150 |
| 19 | T-shirt | 147 |
| 20 | Sneakers | 145 |
| 21 | Boots | 144 |
| 22 | Backpack | 143 |
| 23 | Gloves | 140 |
| 24 | Jeans | 124 |
plt.figure(figsize=(20, 8))
df['Item Purchased'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution de Item purchased')
plt.ylabel("")
plt.tight_layout()
plt.show()
On remarque une répartition plutôt égale de la vente des produits. Le produit le plus vendu a été 171 fois, & le moins vendu 124 fois.
item_revenu = df.groupby('Item Purchased')['Purchase Amount (USD)'].sum()
item_revenu.sort_values(ascending=False)
Item Purchased
Blouse 10410
Shirt 10332
Dress 10320
Pants 10090
Jewelry 10010
Sunglasses 9649
Belt 9635
Scarf 9561
Sweater 9462
Shorts 9433
Skirt 9402
Hat 9375
Coat 9275
Socks 9252
Jacket 9249
T-shirt 9248
Shoes 9240
Sandals 9200
Boots 9018
Handbag 8857
Hoodie 8767
Backpack 8636
Sneakers 8635
Gloves 8477
Jeans 7548
Name: Purchase Amount (USD), dtype: int64
columns_to_display = ['Item Purchased','Purchase Amount (USD)']
df[columns_to_display]
| Item Purchased | Purchase Amount (USD) | |
|---|---|---|
| 0 | Blouse | 53 |
| 1 | Sweater | 64 |
| 2 | Jeans | 73 |
| 3 | Sandals | 90 |
| 4 | Blouse | 49 |
| ... | ... | ... |
| 3895 | Hoodie | 28 |
| 3896 | Backpack | 49 |
| 3897 | Belt | 33 |
| 3898 | Shoes | 77 |
| 3899 | Handbag | 81 |
3900 rows × 2 columns
On constate que le produit qui rapport le plus d’argent est la blouse ce qui est cohérent avec le fait que ça soit l’item le plus vendu et le plus cher.
Les Catégories¶
df['Category'].value_counts()
Category
Clothing 1737
Accessories 1240
Footwear 599
Outerwear 324
Name: count, dtype: int64
# Calculer la distribution des catégories
category_counts = df['Category'].value_counts()
# Tracer un pie chart
category_counts.plot(kind='pie', autopct='%1.1f%%', figsize=(8, 8), colors=sns.color_palette('Set3', len(category_counts)))
# Ajouter un titre
plt.title('Répartition des catégories de produits')
# Afficher le graphique
plt.tight_layout()
plt.show()
La catégories présente en plus grande proprotion est Clothing ( Vêtements) suivi d’Acessories ( Acessoires)
# Regrouper les données par 'Category' et calculer la somme des 'Purchase Amount (USD)'
category_revenue = df.groupby('Category')['Purchase Amount (USD)'].sum().reset_index()
# Trier les résultats par montant décroissant
category_revenue = category_revenue.sort_values(by='Purchase Amount (USD)', ascending=False)
# Afficher le résultat
display(category_revenue)
| Category | Purchase Amount (USD) | |
|---|---|---|
| 1 | Clothing | 104264 |
| 0 | Accessories | 74200 |
| 2 | Footwear | 36093 |
| 3 | Outerwear | 18524 |
La catégorie qui rapporte le plus à l’entreprise est Clothing, ce qui est cohérent avec le fait que ça la catégorie la plus vendue.
Ventes par genre¶
df['Gender'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution par genre')
plt.tight_layout()
Ce sont majoritairement des hommes qui achètent sur ce site.
clothing = df[df['Category'] == 'Clothing']
clothing['Gender'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution par genre')
plt.tight_layout()
accessories = df[df['Category'] == 'Accessories']
accessories['Gender'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution par genre')
plt.tight_layout()
footwear = df[df['Category'] == 'Footwear']
footwear['Gender'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution par genre')
plt.tight_layout()
On remarque que la grande majorité des acheteurs sont des hommes
outerwear = df[df['Category'] == 'Outerwear']
outerwear['Gender'].value_counts().plot(kind='pie',autopct='%1.1f%%')
plt.title('Distribution par genre')
plt.tight_layout()
La répartition des genres par catégories restent approximativement la même pour tous les types d’item
Age des acheteurs¶
df["Age"].describe()
count 3900.000000
mean 44.068462
std 15.207589
min 18.000000
25% 31.000000
50% 44.000000
75% 57.000000
max 70.000000
Name: Age, dtype: float64
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
sns.histplot(data=df, x="Age", kde=True, ax=axes[0])
sns.boxplot(data=df, x="Age")
<Axes: xlabel='Age'>
# Calculer les statistiques de base pour la colonne 'Age'
age_stats = df['Age'].describe()
# Afficher les valeurs du minimum, du maximum et de la médiane
print(f"Min: {age_stats['min']}")
print(f"Max: {age_stats['max']}")
print(f"Median: {age_stats['50%']}")
Min: 18.0
Max: 70.0
Median: 44.0
df_sorted = df.sort_values(by=["Age", "Gender"])
df['Age Group'] = pd.cut(df['Age'], bins=range(18, 80, 10), labels=[f"{i}-{i+9}" for i in range(18, 70, 10)])
# Compter le nombre de personnes par tranche d'âge et genre
# Groupby avec observed=False pour conserver le comportement actuel
age_gender_count = df.groupby(["Age Group", "Gender"], observed=False).size().reset_index(name="Count")
# Graphique en barres
plt.figure(figsize=(10, 6))
sns.barplot(data=age_gender_count, x="Age Group", y="Count", hue="Gender")
palette = sns.color_palette("bright")[::-1]
plt.title("Nombre d'individus par tranche d'âge et par genre")
plt.xlabel("Tranche d'âge")
plt.ylabel("Nombre d'individus")
plt.legend(title="Genre")
plt.show()
# Purchase Amount Distribution
plt.figure(figsize=(12, 5))
sns.set(style="whitegrid")
sns.boxplot(x=df['Purchase Amount (USD)'], color='lightcoral')
plt.title('Boxplot of Purchase Amount', fontsize=16, fontweight='bold')
plt.xlabel('Purchase Amount', fontsize=14)
Text(0.5, 0, 'Purchase Amount')
# Calculer les statistiques de base pour la colonne 'Age'
purchase_stats = df['Purchase Amount (USD)'].describe()
# Afficher les valeurs du minimum, du maximum et de la médiane
print(f"Min: {purchase_stats['min']}")
print(f"Max: {purchase_stats['max']}")
print(f"Median: {purchase_stats['50%']}")
Min: 20.0
Max: 100.0
Median: 60.0
# Créer des catégories d'âge
bins = [18, 20, 30, 40, 50, 60, 70, 100] # Définir les intervalles d'âge
labels = ['18-20', '20-30', '31-40', '41-50', '51-60', '61-70', '71+'] # Noms des catégories
# Ajouter une colonne avec les catégories d'âge
df['Age Group'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)
# Tracer un boxplot des dépenses en fonction des groupes d'âge
plt.figure(figsize=(12, 5))
sns.set(style="whitegrid")
sns.boxplot(x=df['Age Group'], y=df['Purchase Amount (USD)'], color='lightcoral')
# Ajouter les titres et labels
plt.title('Boxplot of Purchase Amount by Age Group', fontsize=16, fontweight='bold')
plt.xlabel('Age Group', fontsize=14)
plt.ylabel('Purchase Amount (USD)', fontsize=14)
# Affichage final
plt.tight_layout()
plt.show()
On remarque l’âge a peu d’influence sur le montant des achats.
size_counts = df['Size'].value_counts().reset_index()
size_counts.columns = ['Size', 'Count']
# Graphique en barres
plt.figure(figsize=(10, 6))
sns.barplot(data=size_counts, x="Size", y="Count", hue="Size")
palette = sns.color_palette("bright")[::-1]
plt.title("Taille les plus vendues")
plt.xlabel("Taille")
plt.ylabel("Nombre de produits vendus")
plt.show()
La taille M est de loin la plus vendue.
Couleurs les plus vendues¶
df["Color"].value_counts(normalize=True).reset_index()
| Color | proportion | |
|---|---|---|
| 0 | Olive | 0.045385 |
| 1 | Yellow | 0.044615 |
| 2 | Silver | 0.044359 |
| 3 | Teal | 0.044103 |
| 4 | Green | 0.043333 |
| 5 | Black | 0.042821 |
| 6 | Cyan | 0.042564 |
| 7 | Violet | 0.042564 |
| 8 | Gray | 0.040769 |
| 9 | Maroon | 0.040513 |
| 10 | Orange | 0.039487 |
| 11 | Charcoal | 0.039231 |
| 12 | Pink | 0.039231 |
| 13 | Blue | 0.038974 |
| 14 | Magenta | 0.038974 |
| 15 | Purple | 0.038718 |
| 16 | Peach | 0.038205 |
| 17 | Red | 0.037949 |
| 18 | Beige | 0.037692 |
| 19 | Indigo | 0.037692 |
| 20 | Lavender | 0.037692 |
| 21 | Turquoise | 0.037179 |
| 22 | White | 0.036410 |
| 23 | Brown | 0.036154 |
| 24 | Gold | 0.035385 |
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Graphique de barres
sns.countplot(data=df, x="Color", ax=axes[0])
axes[0].set_xticks(range(len(df["Color"].unique()))) # Définir les ticks
axes[0].set_xticklabels(axes[0].get_xticklabels(), rotation=90)
# Diagramme circulaire
color_counts = df["Color"].value_counts() # Assurez-vous que color_counts est défini
axes[1].pie(color_counts, labels=color_counts.index, startangle=90)
# Affichage des graphiques
plt.tight_layout()
plt.show()
On constate qu’il y a une répartition plutôt égale des couleurs des items vendus
Ventes par saison¶
season_counts = df["Season"].value_counts()
season_counts
Season
Spring 999
Fall 975
Winter 971
Summer 955
Name: count, dtype: int64
season = df["Season"].value_counts(normalize=1).reset_index()
# Count popular payment methods
season.columns = ['Season', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
season,
names='Season',
values='Count',
title='Répartition des achats en en fontion des sainsons'
)
# Ajuster la taille et le titre
fig.update_layout(
title={'text': 'Répartition des achats en en fontion des sainsons', 'x': 0.5, 'font': {'size': 18}}, # Taille du titre
width=800, # Largeur du graphique
height=600 # Hauteur du graphique
)
# Afficher le graphique
fig.show()
On remarque la saison n’influe pas sur les ventes du site.
Notations¶
df["Review Rating"].describe()
count 3900.000000
mean 3.749949
std 0.716223
min 2.500000
25% 3.100000
50% 3.700000
75% 4.400000
max 5.000000
Name: Review Rating, dtype: float64
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
sns.histplot(data=df, x="Review Rating", ax=axes[0], kde=True)
sns.boxplot(data=df, x="Review Rating", ax=axes[1])
<Axes: xlabel='Review Rating'>
La moyenne des avis est 3,75, avec un écart type de 0,72, indiquant une faible dispersion. Cela signifie que la plupart des avis sont concentrés entre 3,03 et 4,47. Les quartiles montrent que 50% des avis sont inférieurs à 3,7, mais que 75% sont inférieurs ou égaux à 4,4, ce qui reflète une appréciation généralement positive, avec peu de variations extrêmes.
Acheteurs ayant un compte¶
# Compter les utilisateurs selon leur statut d'abonnement
subscription = df["Subscription Status"].value_counts().reset_index()
subscription.columns = ['Subscription Status', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
subscription,
names='Subscription Status',
values='Count',
title='Répartition des acheteurs ayant un compte',
hole=0.4 # Optionnel : pour un graphique en anneau
)
# Ajuster la mise en page et ajouter des pourcentages
fig.update_traces(
textinfo='percent+label', # Affiche le pourcentage et l'étiquette
hoverinfo='label+value+percent' # Infos au survol : étiquette, valeur, pourcentage
)
# Ajuster le titre et la taille
fig.update_layout(
title={'text': 'Répartition des acheteurs ayant un compte', 'x': 0.5, 'font': {'size': 18}},
width=800,
height=600
)
# Afficher le graphique
fig.show()
La grande majorité des acheteurs n’ont pas de compte sur le site
Acheteurs qui profitent des réductions proposées¶
df.columns
Index(['Customer ID', 'Age', 'Gender', 'Item Purchased', 'Category',
'Purchase Amount (USD)', 'Location', 'Size', 'Color', 'Season',
'Review Rating', 'Subscription Status', 'Payment Method',
'Shipping Type', 'Discount Applied', 'Promo Code Used',
'Previous Purchases', 'Preferred Payment Method',
'Frequency of Purchases', 'Age Group'],
dtype='object')
# Compter les utilisateurs selon leur statut d'abonnement
promo_code = df["Promo Code Used"].value_counts().reset_index()
promo_code.columns = ['Promo Code Used', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
promo_code,
names='Promo Code Used',
values='Count',
title='Répartition des acheteurs utilisant un code promo',
hole=0.4 # Optionnel : pour un graphique en anneau
)
# Ajuster la mise en page et ajouter des pourcentages
fig.update_traces(
textinfo='percent+label', # Affiche le pourcentage et l'étiquette
hoverinfo='label+value+percent' # Infos au survol : étiquette, valeur, pourcentage
)
# Ajuster le titre et la taille
fig.update_layout(
title={'text': 'Répartition des acheteurs utilisant un code promo', 'x': 0.5, 'font': {'size': 18}},
width=800,
height=600
)
# Afficher le graphique
fig.show()
Une petite majorité des utilisateurs utilisent les Codes Promos proposés par le site
Réductions appliquées¶
# Compter les utilisateurs selon leur statut d'abonnement
discount = df["Discount Applied"].value_counts().reset_index()
discount.columns = ['Discount Applied', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
discount,
names='Discount Applied',
values='Count',
title='Répartition des acheteurs ayant une remise',
)
# Ajuster la mise en page et ajouter des pourcentages
fig.update_traces(
textinfo='percent+label', # Affiche le pourcentage et l'étiquette
hoverinfo='label+value+percent' # Infos au survol : étiquette, valeur, pourcentage
)
# Ajuster le titre et la taille
fig.update_layout(
title={'text': 'Répartition des acheteurs ayant une remise', 'x': 0.5, 'font': {'size': 18}},
width=800,
height=600
)
# Afficher le graphique
fig.show()
La majorité des acheteurs n’ont pas de remise
Visualisation du nombre d’achats déjà réalisés¶
df["Previous Purchases"].describe()
count 3900.000000
mean 25.351538
std 14.447125
min 1.000000
25% 13.000000
50% 25.000000
75% 38.000000
max 50.000000
Name: Previous Purchases, dtype: float64
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
sns.histplot(data=df, x="Previous Purchases", ax=axes[0], kde=True)
sns.boxplot(data=df, x="Previous Purchases", ax=axes[1])
<Axes: xlabel='Previous Purchases'>
L’écart type des achats précédents est 14,45, ce qui indique une variabilité relativement importante autour de la moyenne 25,35. La plupart des données (environ 68%, si la distribution est normale) se situent dans l’intervalle approximatif [10,9 ; 39,8], tandis que les quartiles montrent que :
25% des achats sont inférieurs à 13.
50% sont inférieurs à 25.
75% sont inférieurs à 38. Cela signifie que les achats précédents sont concentrés entre 13 et 38, mais avec une dispersion notable autour de la moyenne.
df["Frequency of Purchases"].describe()
count 3900
unique 7
top Every 3 Months
freq 584
Name: Frequency of Purchases, dtype: object
fig, axes = plt.subplots(1, 2, figsize=(15, 5))
sns.histplot(data=df, x="Frequency of Purchases", ax=axes[0], kde=True)
sns.boxplot(data=df, x="Frequency of Purchases", ax=axes[1])
<Axes: xlabel='Frequency of Purchases'>
Méthodes de paiement¶
# Count popular payment methods
payment_counts = df['Payment Method'].value_counts().reset_index()
payment_counts.columns = ['Payment Method', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
payment_counts,
names='Payment Method',
values='Count',
title='Répartition des méthodes de paiement populaires'
)
# Ajuster la taille et le titre
fig.update_layout(
title={'text': "Répartition des méthodes de paiement", 'x': 0.5, 'font': {'size': 18}}, # Taille du titre
width=800, # Largeur du graphique
height=600 # Hauteur du graphique
)
# Afficher le graphique
fig.show()
On peut remarquer qu’il n’y a pas de différence notable au niveau de la proportion des méthodes de paiement
# Créer des catégories d'âge
bins = [18, 20, 30, 40, 50, 60, 70, 100] # Définir les intervalles d'âge
labels = ['18-20', '20-30', '31-40', '41-50', '51-60', '61-70', '71+'] # Noms des catégories
# Ajouter une colonne avec les catégories d'âge
df['Age Group'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)
# Tracer un boxplot des dépenses en fonction des groupes d'âge
plt.figure(figsize=(12, 5))
sns.set(style="whitegrid")
sns.boxplot(x=df['Age Group'], y=df['Payment Method'], color='lightcoral')
# Ajouter les titres et labels
plt.title('Boxplot of Payment Method by Age Group', fontsize=16, fontweight='bold')
plt.xlabel('Age Group', fontsize=14)
plt.ylabel('Purchase Amount (USD)', fontsize=14)
# Affichage final
plt.tight_layout()
plt.show()
On constate que chez les 20-30 ans et les 41-50 ans le mode de paiement le plus utilisé est Paypal, et que c’est le Cash pour le reste des transhces d’âge.
Mode de livraison¶
# Count popular payment methods
shipping = df['Shipping Type'].value_counts().reset_index()
shipping.columns = ['Shipping Type', 'Count']
# Créer un diagramme circulaire
fig = px.pie(
shipping,
names='Shipping Type',
values='Count',
title='Répartition des modes d`envoie populaires'
)
# Ajuster la taille et le titre
fig.update_layout(
title={'text': "Répartition des modes d`envoie populaires", 'x': 0.5, 'font': {'size': 18}}, # Taille du titre
width=800, # Largeur du graphique
height=600 # Hauteur du graphique
)
# Afficher le graphique
fig.show()
# Créer des catégories d'âge
bins = [18, 20, 30, 40, 50, 60, 70, 100] # Définir les intervalles d'âge
labels = ['18-20', '20-30', '31-40', '41-50', '51-60', '61-70', '71+'] # Noms des catégories
# Ajouter une colonne avec les catégories d'âge
df['Age Group'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)
# Tracer un boxplot des dépenses en fonction des groupes d'âge
plt.figure(figsize=(12, 5))
sns.set(style="whitegrid")
sns.boxplot(x=df['Age Group'], y=df['Shipping Type'], color='lightcoral')
# Ajouter les titres et labels
plt.title("Boxplot des méthodes d`envoi par groupe d'age", fontsize=16, fontweight='bold')
plt.xlabel('Age Group', fontsize=14)
plt.ylabel('Purchase Amount (USD)', fontsize=14)
# Affichage final
plt.tight_layout()
plt.show()
On remarque que les 20-30 ans et les personnes de plus de 71 ans ont une préférence pour la livraison standard, tandis que les autres groupes d’âge préfère la livraion à J+1.